package com.hokai.base.config;

import java.util.LinkedHashMap;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
* @ClassName: ShiroConfiguration  
* @Description: TODO(shiro的配置类)  
* @author LinYing  
* @date 2018年9月14日  
 */
@Configuration
public class ShiroConfiguration {
	
	

	// shiro的拦截器工厂类
	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
		ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		bean.setSecurityManager(manager);
		// 配置controller里面登录的url和
		bean.setLoginUrl("/#/");

		// 配置权限链接
		LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		filterChainDefinitionMap.put("/login", "anon"); // anon:表示可以匿名访问
		filterChainDefinitionMap.put("/loginUser", "anon");
		filterChainDefinitionMap.put("/logout*", "anon");
		// 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
		filterChainDefinitionMap.put("/logout", "logout");

		// 真正使用的时候可以用从数据库获取所有的菜单url进行添加进去
		// filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
		filterChainDefinitionMap.put("/*/*", "authc");
		filterChainDefinitionMap.put("/*.*", "authc");
		bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		System.out.println("shiro拦截器工厂类注册成功");
		return bean;
	}

	// 配置核心安全事务管理器
	@Bean(name = "securityManager")
	public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
		System.err.println("--------------shiro已经加载----------------3");
		DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
		// 设置Realm，用于获取认证凭证
		manager.setRealm(authRealm);
		// 注入EhCacheManager缓存管理器
		// manager.setCacheManager(ehCacheManager());
		// 注入Cookie(记住我)管理器(remenberMeManager)
		manager.setRememberMeManager(rememberMeManager());
		return manager;
	}

	// 配置自定义的权限登录器
	@Bean(name = "authRealm")
	public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
		System.err.println("--------------shiro已经加载----------------2");
		AuthRealm authRealm = new AuthRealm();
		// 设置自定义的密码比较器
		authRealm.setCredentialsMatcher(matcher);

		// 启用缓存,默认是false
		authRealm.setCachingEnabled(true);
		// 启用身份验证缓存，即缓存AuthenticationInfo信息，默认false；
		authRealm.setAuthenticationCachingEnabled(true);
		// 缓存AuthenticationInfo信息的缓存名称,即配置在ehcache.xml中的cache name
		authRealm.setAuthenticationCacheName("authenticationCache");

		// 启用授权缓存，即缓存AuthorizationInfo信息，默认false；
		authRealm.setAuthorizationCachingEnabled(true);
		// 缓存AuthorizationInfo信息的缓存名称；
		authRealm.setAuthorizationCacheName("authorizationCache");

		return authRealm;
	}

	// 配置自定义的密码比较器
	@Bean(name = "credentialsMatcher")
	public CredentialsMatcher credentialsMatcher() {
		System.err.println("--------------shiro已经加载----------------1");
		return new CredentialsMatcher();
	}

	/**
	 * Shiro生命周期处理器
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	/**
	 * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions) 需要配置以下两个类
	 */
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			@Qualifier("securityManager") SecurityManager manager) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(manager);
		return advisor;
	}

	/**
	 * Shiro CacheManager 定义 Shiro 缓存管理器 需要加入到安全管理器：securityManager
	 */
	/*
	 * @Bean public EhCacheManager ehCacheManager() {
	 * System.err.println("--------------shiro已经加载----------------4");
	 * EhCacheManager cacheManager = new EhCacheManager();
	 * cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml"); return
	 * cacheManager; }
	 */

	/**
	 * cookie管理器
	 * 
	 * @return
	 */
	@Bean
	public CookieRememberMeManager rememberMeManager() {
		System.err.println("注入Shiro的记住我(CookieRememberMeManager)管理器-->rememberMeManager");
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		// rememberme cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度（128 256 512 位），通过以下代码可以获取
		// KeyGenerator keygen = KeyGenerator.getInstance("AES");
		// SecretKey deskey = keygen.generateKey();
		// System.out.println(Base64.encodeToString(deskey.getEncoded()));
		byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
		// cookieRememberMeManager.setCipherKey(cipherKey);
		cookieRememberMeManager.setCookie(rememberMeCookie());
		return cookieRememberMeManager;
	}

	@Bean
	public SimpleCookie rememberMeCookie() {
		// 这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
		SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
		// 如果httyOnly设置为true，则客户端不会暴露给客户端脚本代码，使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击；
		simpleCookie.setHttpOnly(true);
		// 记住我cookie生效时间,默认30天 ,单位秒：60 * 60 * 24 * 30
		simpleCookie.setMaxAge(259200);
		return simpleCookie;
	}
	
//	@Bean
//	public TPermissionService tPermissionService() {
//		return new TPermissionServiceImpl();
//	}

}
